from typing import List, Optional, Any, Dict
from fastapi import APIRouter, Depends, HTTPException, Query, Path, Request
from sqlalchemy.orm import Session, joinedload
from sqlalchemy import and_, or_
from datetime import datetime
import json

from database.db import get_db
from models.task import Task, TaskRoute, TaskStatusEnum, TaskExecuteTypeEnum
from models.task_drone import TaskDrone
from models import User, FlightRoute
from models.drone import Drone
from schemas.task import (
    TaskSchema, TaskCreate, TaskUpdate, TaskList, 
    TaskStatusUpdate, TaskProgressUpdate
)
from schemas import ResponseModel, PaginatedResponse
from api.deps import get_current_active_user, get_client_ip
from utils import log_operation
from utils.task_to_mission_converter import convert_task_to_mission

router = APIRouter()


@router.get("", response_model=TaskList)
async def get_tasks(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页大小"),
    status: Optional[str] = Query(None, description="任务状态过滤"),
    priority: Optional[str] = Query(None, description="优先级过滤"),
   responsible_person_id: Optional[int] = Query(None, description="负责人ID过滤"),
    keyword: Optional[str] = Query(None, description="搜索关键词"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """获取任务列表"""
    # 构建查询条件
    query = db.query(Task)
    
    if status:
        query = query.filter(Task.status == status)
    
    if priority:
        query = query.filter(Task.priority == priority)
    
    if responsible_person_id:
         query = query.filter(Task.responsible_person_id == responsible_person_id)
    
    if keyword:
        query = query.filter(Task.name.contains(keyword) | Task.description.contains(keyword))
    
    # 获取总数
    total = query.count()
    
    # 分页查询
    tasks = query.options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).order_by(Task.created_at.desc()).offset((page - 1) * page_size).limit(page_size).all()
    
    # 转换为响应模型
    task_schemas = []
    for task in tasks:
        task_dict = {
            "id": task.id,
            "name": task.name,
            "description": task.description,
            "priority": task.priority,
            "execute_type": task.execute_type,
            "scheduled_time": task.scheduled_time,
            "responsible_person_id": task.responsible_person_id,
            "status": task.status,
            "progress": task.progress,
            "detection_model_ids": task.detection_model_ids,
            "trigger_conditions": task.trigger_conditions,
            "exception_strategies": task.exception_strategies,
            "start_time": task.start_time,
            "end_time": task.end_time,
            "created_by": task.created_by,
            "created_at": task.created_at,
            "updated_at": task.updated_at,
            "负责人": task.负责人,
            "task_routes": task.task_routes,
            "task_drones": task.task_drones
        }
        task_schemas.append(TaskSchema(**task_dict))
    
    return TaskList(
        items=task_schemas,
        total=total,
        page=page,
        page_size=page_size
    )


@router.get("/{task_id}", response_model=TaskSchema)
async def get_task(
    task_id: int = Path(..., description="任务ID"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """获取任务详情"""
    task = db.query(Task).options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == task_id).first()
    
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 转换为响应模型
    task_dict = {
        "id": task.id,
        "name": task.name,
        "description": task.description,
        "priority": task.priority,
        "execute_type": task.execute_type,
        "scheduled_time": task.scheduled_time,
        "responsible_person_id": task.responsible_person_id,
        "status": task.status,
        "progress": task.progress,
        "detection_model_ids": task.detection_model_ids,
        "trigger_conditions": task.trigger_conditions,
        "exception_strategies": task.exception_strategies,
        "start_time": task.start_time,
        "end_time": task.end_time,
        "created_by": task.created_by,
        "created_at": task.created_at,
        "updated_at": task.updated_at,
        "负责人": task.负责人,
        "task_routes": task.task_routes,
        "task_drones": task.task_drones
    }
    
    return TaskSchema(**task_dict)


@router.get("/{task_id}/to-mission", response_model=ResponseModel[Dict[str, Any]])
async def convert_task_to_mission_json(
    task_id: int = Path(..., description="任务ID"),
    drone_id: str = Query(..., description="无人机ID"),
    mission_id: int = Query(5001, description="任务ID"),
    speed: float = Query(3.0, ge=0.1, le=20.0, description="飞行速度"),
    takeoff_height: float = Query(10.0, ge=1.0, le=500.0, description="起飞高度"),
    yaw_mode: int = Query(0, ge=0, le=3, description="偏航模式"),
    yaw_angle: float = Query(0.0, ge=-360.0, le=360.0, description="偏航角度"),
    end_z: float = Query(0.8, ge=0.5, le=500.0, description="结束高度"),
    is_gps: bool = Query(True, description="是否为GPS模式"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """
    将任务转换为PX4 Mission JSON格式
    用于生成可以直接发送给无人机的任务指令
    """
    # 获取任务信息
    task = db.query(Task).options(
        joinedload(Task.responsible_person),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == task_id).first()
    
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 构建任务数据字典
    task_dict = {
        "id": task.id,
        "name": task.name,
        "description": task.description,
        "priority": task.priority,
        "execute_type": task.execute_type,
        "scheduled_time": task.scheduled_time,
        "responsible_person_id": task.responsible_person_id,
        "status": task.status,
        "progress": task.progress,
        "detection_model_ids": task.detection_model_ids,
        "trigger_conditions": task.trigger_conditions,
        "exception_strategies": task.exception_strategies,
        "route_coordinates": task.route_coordinates,
        "start_time": task.start_time,
        "end_time": task.end_time,
        "created_by": task.created_by,
        "created_at": task.created_at,
        "updated_at": task.updated_at,
    }
    
    # 构建任务航线信息
    task_routes = []
    for tr in task.task_routes:
        route_data = {
            "id": tr.id,
            "route_id": tr.route_id,
            "order_index": tr.order_index,
            "route": None
        }
        if tr.route:
            route_data["route"] = {
                "waypoints": tr.route.waypoints,
                "name": tr.route.name,
                "description": tr.route.description
            }
        task_routes.append(route_data)
    
    task_dict["task_routes"] = task_routes
    
    try:
        # 转换为mission格式
        result = convert_task_to_mission(
            task_data=task_dict,
            drone_id=drone_id,
            mission_id=mission_id,
            speed=speed,
            takeoff_height=takeoff_height,
            yaw_mode=yaw_mode,
            yaw_angle=yaw_angle,
            end_z=end_z,
            is_gps=is_gps
        )
        
        return ResponseModel(data=result)
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"转换任务格式时出错: {str(e)}")



@router.post("", response_model=TaskSchema)
async def create_task(
    request: Request,
    task_data: TaskCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """创建任务"""
    ip_address = get_client_ip(request)
    
    try:
        # 验证航线是否存在
        routes = db.query(FlightRoute).filter(FlightRoute.id.in_(task_data.route_ids)).all()
        if len(routes) != len(task_data.route_ids):
            raise HTTPException(status_code=400, detail="部分航线不存在")
        
        # 收集航线坐标信息
        route_coordinates = []
        for route in routes:
            route_coordinates.append({
                "route_id": route.id,
                "route_name": route.name,
                "waypoints": route.waypoints
            })
        
        # 创建任务
        new_task = Task(
            name=task_data.name,
            description=task_data.description,
            priority=task_data.priority,
            execute_type=task_data.execute_type,
            scheduled_time=task_data.scheduled_time,
            responsible_person_id=task_data.responsible_person_id,
            detection_model_ids=task_data.detection_model_ids,
            trigger_conditions=task_data.trigger_conditions,
            exception_strategies=task_data.exception_strategies,
            route_coordinates=route_coordinates,
            created_by=current_user.id
        )
        
        # 验证负责人是否存在
        if task_data.responsible_person_id:
            负责人 = db.query(User).filter(User.id == task_data.responsible_person_id).first()
            if not 负责人:
                raise HTTPException(status_code=400, detail="负责人不存在")
        
        # 创建任务
        new_task = Task(
            name=task_data.name,
            description=task_data.description,
            priority=task_data.priority,
            execute_type=task_data.execute_type,
            scheduled_time=task_data.scheduled_time,
            responsible_person_id=task_data.responsible_person_id,
            detection_model_ids=task_data.detection_model_ids,
            trigger_conditions=task_data.trigger_conditions,
            exception_strategies=task_data.exception_strategies,
            created_by=current_user.id
        )
        
        db.add(new_task)
        db.flush()  # 获取任务ID但不提交事务
        
        # 创建任务航线关联
        route_order = task_data.route_order or list(range(len(task_data.route_ids)))
        for i, route_id in enumerate(task_data.route_ids):
            task_route = TaskRoute(
                task_id=new_task.id,
                route_id=route_id,
                order_index=route_order[i] if i < len(route_order) else i
            )
            db.add(task_route)
        
        # 创建任务无人机关联
        # 验证无人机是否存在
        drones = db.query(Drone).filter(Drone.id.in_(task_data.drone_ids)).all()
        if len(drones) != len(task_data.drone_ids):
            raise HTTPException(status_code=400, detail="部分无人机不存在")
        
        # 创建无人机关联，默认第一个为主用
        for idx, drone_id in enumerate(task_data.drone_ids):
            task_drone = TaskDrone(
                task_id=new_task.id,
                drone_id=drone_id,
                is_primary=idx == 0  # 第一个无人机设为主用
            )
            db.add(task_drone)
        
        # 如果是立即执行的任务，自动设置为已计划状态
        if task_data.execute_type == TaskExecuteTypeEnum.IMMEDIATE:
            new_task.status = TaskStatusEnum.SCHEDULED
        
        db.commit()
        db.refresh(new_task)
        
        # 记录创建任务成功日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_task",
            operation_content=f"用户 {current_user.username} 创建任务：{task_data.name}（ID: {new_task.id}）",
            success=1
        )
    except HTTPException:
        db.rollback()
        # 记录创建任务失败日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_task",
            operation_content=f"用户 {current_user.username} 创建任务失败：{task_data.name}",
            success=0
        )
        raise
    except Exception as e:
        db.rollback()
        # 记录创建任务异常日志
        log_operation(
            db=db,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=ip_address,
            operation_type="create_task",
            operation_content=f"用户 {current_user.username} 创建任务异常：{task_data.name}，错误：{str(e)}",
            success=0
        )
        raise HTTPException(
            status_code=500,
            detail="创建任务过程中发生错误"
        )
    
    # 重新查询以包含关联数据
    new_task = db.query(Task).options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == new_task.id).first()
    
    # 转换为响应模型
    task_dict = {
        "id": new_task.id,
        "name": new_task.name,
        "description": new_task.description,
        "priority": new_task.priority,
        "execute_type": new_task.execute_type,
        "scheduled_time": new_task.scheduled_time,
        "responsible_person_id": new_task.responsible_person_id,
        "status": new_task.status or TaskStatusEnum.DRAFT,
        "progress": new_task.progress or 0,
        "detection_model_ids": new_task.detection_model_ids,
        "trigger_conditions": new_task.trigger_conditions,
        "exception_strategies": new_task.exception_strategies,
        "start_time": new_task.start_time,
        "end_time": new_task.end_time,
        "created_by": new_task.created_by,
        "created_at": new_task.created_at,
        "updated_at": new_task.updated_at,
        "负责人": new_task.负责人,
        "task_routes": new_task.task_routes,
        "task_drones": new_task.task_drones
    }
    
    return TaskSchema(**task_dict)


@router.put("/{task_id}", response_model=TaskSchema)
async def update_task(
    task_id: int = Path(..., description="任务ID"),
    task_data: TaskUpdate = ...,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """更新任务"""
    # 获取任务
    task = db.query(Task).filter(Task.id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 检查任务状态是否允许修改
    if task.status in [TaskStatusEnum.COMPLETED, TaskStatusEnum.CANCELLED, TaskStatusEnum.FAILED]:
        raise HTTPException(status_code=400, detail="已完成或已取消的任务无法修改")
    
    # 更新基本字段
    update_data = task_data.model_dump(exclude_unset=True)
    
    # 处理特殊字段
    if "route_ids" in update_data and "route_order" in update_data:
        # 验证航线是否存在
        route_ids = update_data.pop("route_ids")
        route_order = update_data.pop("route_order")
        
        routes = db.query(FlightRoute).filter(FlightRoute.id.in_(route_ids)).all()
        if len(routes) != len(route_ids):
            raise HTTPException(status_code=400, detail="部分航线不存在")
        
        # 收集航线坐标信息
        route_coordinates = []
        for route in routes:
            route_coordinates.append({
                "route_id": route.id,
                "route_name": route.name,
                "waypoints": route.waypoints
            })
        
        # 更新航线坐标信息
        task.route_coordinates = route_coordinates
        
        # 删除旧的航线关联
        db.query(TaskRoute).filter(TaskRoute.task_id == task_id).delete()
        
        # 创建新的航线关联
        for i, route_id in enumerate(route_ids):
            task_route = TaskRoute(
                task_id=task_id,
                route_id=route_id,
                order_index=route_order[i] if i < len(route_order) else i
            )
            db.add(task_route)
    
    # 处理无人机关联
    if "drone_ids" in update_data:
        drone_ids = update_data.pop("drone_ids")
        
        # 删除旧的无人机关联
        db.query(TaskDrone).filter(TaskDrone.task_id == task_id).delete()
        
        # 如果提供了新的无人机ID列表，创建新的关联
        if drone_ids:
            # 验证无人机是否存在
            drones = db.query(Drone).filter(Drone.id.in_(drone_ids)).all()
            if len(drones) != len(drone_ids):
                raise HTTPException(status_code=400, detail="部分无人机不存在")
            
            # 创建无人机关联，默认第一个为主用
            for idx, drone_id in enumerate(drone_ids):
                task_drone = TaskDrone(
                    task_id=task_id,
                    drone_id=drone_id,
                    is_primary=idx == 0  # 第一个无人机设为主用
                )
                db.add(task_drone)
    
    # 验证负责人是否存在
    if "responsible_person_id" in update_data and update_data["responsible_person_id"]:
        负责人 = db.query(User).filter(User.id == update_data["responsible_person_id"]).first()
        if not 负责人:
            raise HTTPException(status_code=400, detail="负责人不存在")
    
    # 更新其他字段
    for field, value in update_data.items():
        setattr(task, field, value)
    
    db.commit()
    db.refresh(task)
    
    # 重新查询以包含关联数据
    task = db.query(Task).options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == task.id).first()
    
    # 转换为响应模型
    task_dict = {
        "id": task.id,
        "name": task.name,
        "description": task.description,
        "priority": task.priority,
        "execute_type": task.execute_type,
        "scheduled_time": task.scheduled_time,
        "responsible_person_id": task.responsible_person_id,
        "status": task.status,
        "progress": task.progress,
        "detection_model_ids": task.detection_model_ids,
        "trigger_conditions": task.trigger_conditions,
        "exception_strategies": task.exception_strategies,
        "start_time": task.start_time,
        "end_time": task.end_time,
        "created_by": task.created_by,
        "created_at": task.created_at,
        "updated_at": task.updated_at,
        "负责人": task.负责人,
        "task_routes": task.task_routes,
        "task_drones": task.task_drones
    }
    
    return TaskSchema(**task_dict)


@router.put("/{task_id}/status", response_model=TaskSchema)
async def update_task_status(
    task_id: int = Path(..., description="任务ID"),
    status_update: TaskStatusUpdate = ...,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """更新任务状态"""
    task = db.query(Task).filter(Task.id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 状态转换逻辑
    if task.status == TaskStatusEnum.DRAFT:
        if status_update.status not in [TaskStatusEnum.SCHEDULED, TaskStatusEnum.CANCELLED]:
            raise HTTPException(status_code=400, detail="草稿状态只能转换为已计划或已取消")
    elif task.status == TaskStatusEnum.SCHEDULED:
        if status_update.status not in [TaskStatusEnum.IN_PROGRESS, TaskStatusEnum.CANCELLED]:
            raise HTTPException(status_code=400, detail="已计划状态只能转换为进行中或已取消")
        # 开始执行任务
        if status_update.status == TaskStatusEnum.IN_PROGRESS:
            task.start_time = datetime.now()
    elif task.status == TaskStatusEnum.IN_PROGRESS:
        if status_update.status not in [TaskStatusEnum.PAUSED, TaskStatusEnum.COMPLETED, TaskStatusEnum.FAILED]:
            raise HTTPException(status_code=400, detail="进行中状态只能转换为暂停、已完成或失败")
        # 完成任务
        if status_update.status == TaskStatusEnum.COMPLETED:
            task.end_time = datetime.now()
            task.progress = 100
        elif status_update.status == TaskStatusEnum.FAILED:
            task.end_time = datetime.now()
    elif task.status == TaskStatusEnum.PAUSED:
        if status_update.status not in [TaskStatusEnum.IN_PROGRESS, TaskStatusEnum.CANCELLED]:
            raise HTTPException(status_code=400, detail="暂停状态只能转换为进行中或已取消")
    elif task.status in [TaskStatusEnum.COMPLETED, TaskStatusEnum.CANCELLED, TaskStatusEnum.FAILED]:
        raise HTTPException(status_code=400, detail="已完成、已取消或失败的任务状态无法修改")
    
    task.status = status_update.status
    db.commit()
    db.refresh(task)
    
    # 重新查询以包含关联数据
    task = db.query(Task).options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == task.id).first()
    
    # 转换为响应模型
    task_dict = {
        "id": task.id,
        "name": task.name,
        "description": task.description,
        "priority": task.priority,
        "execute_type": task.execute_type,
        "scheduled_time": task.scheduled_time,
        "responsible_person_id": task.responsible_person_id,
        "status": task.status,
        "progress": task.progress,
        "detection_model_ids": task.detection_model_ids,
        "trigger_conditions": task.trigger_conditions,
        "exception_strategies": task.exception_strategies,
        "start_time": task.start_time,
        "end_time": task.end_time,
        "created_by": task.created_by,
        "created_at": task.created_at,
        "updated_at": task.updated_at,
        "responsible_person": task.responsible_person,
        "task_routes": task.task_routes,
        "task_drones": task.task_drones
    }
    
    return TaskSchema(**task_dict)


@router.put("/{task_id}/progress", response_model=TaskSchema)
async def update_task_progress(
    task_id: int = Path(..., description="任务ID"),
    progress_update: TaskProgressUpdate = ...,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """更新任务进度"""
    task = db.query(Task).filter(Task.id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 只有进行中或暂停的任务可以更新进度
    if task.status not in [TaskStatusEnum.IN_PROGRESS, TaskStatusEnum.PAUSED]:
        raise HTTPException(status_code=400, detail="只有进行中或暂停的任务可以更新进度")
    
    task.progress = progress_update.progress
    
    # 如果进度达到100%，自动完成任务
    if progress_update.progress >= 100:
        task.status = TaskStatusEnum.COMPLETED
        task.progress = 100
        task.end_time = datetime.now()
    
    db.commit()
    db.refresh(task)
    
    # 重新查询以包含关联数据
    task = db.query(Task).options(
        joinedload(Task.负责人),
        joinedload(Task.task_routes).joinedload(TaskRoute.route),
        joinedload(Task.task_drones).joinedload(TaskDrone.drone)
    ).filter(Task.id == task.id).first()
    
    # 转换为响应模型
    task_dict = {
        "id": task.id,
        "name": task.name,
        "description": task.description,
        "priority": task.priority,
        "execute_type": task.execute_type,
        "scheduled_time": task.scheduled_time,
        "responsible_person_id": task.responsible_person_id,
        "status": task.status,
        "progress": task.progress,
        "detection_model_ids": task.detection_model_ids,
        "trigger_conditions": task.trigger_conditions,
        "exception_strategies": task.exception_strategies,
        "start_time": task.start_time,
        "end_time": task.end_time,
        "created_by": task.created_by,
        "created_at": task.created_at,
        "updated_at": task.updated_at,
        "负责人": task.负责人,
        "task_routes": task.task_routes,
        "task_drones": task.task_drones
    }
    
    return TaskSchema(**task_dict)


@router.delete("/{task_id}")
async def delete_task(
    task_id: int = Path(..., description="任务ID"),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """删除任务"""
    task = db.query(Task).filter(Task.id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail="任务不存在")
    
    # 只有草稿或已取消的任务可以删除
    if task.status not in [TaskStatusEnum.DRAFT, TaskStatusEnum.CANCELLED]:
        raise HTTPException(status_code=400, detail="只有草稿或已取消的任务可以删除")
    
    db.delete(task)
    db.commit()
    
    return {"message": "任务删除成功"}